EFI TCG2 protocol in U-Boot and QEMU

Posted on Tue 31 August 2021 in UEFI • 5 min read

Do I need a TPM?

I won't go into details regarding why a TPM is useful. There is an excellent article from Matthew Garrett on that, but the short answer is "yes you do".

U-Boot Support

There's a spec defining a standard interface to the TPM on an UEFI platform. It's purpose is to define APIs and provide information, for things like, is a TPM present, which PCR banks are active, change active PCR banks, obtain the TCG boot log, extend hashes to PCRs, and append events to the TCG boot log etc.

U-Boot recently got support for this as well as support for the TCG PC Client Platform Firmware Profile.

Patches can be found here, here and here.

Finding an Arm device with with a TPMv2 can prove hard. So it would be useful to emulate that in software. If you have a board with an RPMB and OP-TEE support, I suggest you try Microsoft's fTPM. However testing that in QEMU won't work since it lacks RPMB emulation. Luckily there's another solution.

Using SWTPM

SWTPM is a TPM emulator that works under QEMU. It provides a memory mapped device which adheres to the TCG TPM Interface Specification. The problem is that U-Boot had no support for memory mapped TPMs, which is exactly what this patchset does.

Building U-Boot

At the time of this article the U-Boot patches are under review, so we need to apply them manually.

So download the patches prepare your U-Boot binary. Patches are now in U-Boot mainline and the arm64 defconfig has the required config options enabled.

git clone https://github.com/u-boot/u-boot.git
pushd u-boot
make qemu_arm64_defconfig
make menuconfig

We need to enable the TPMv2 support in U-Boot CONFIG_TPM, CONFIG_CMD_TPM, CONFIG_TPM2_MMIO must be enabled. Once those are selected CONFIG_EFI_TCG2_PROTOCOL should be automatically included. Make sure you enable CONFIG_CMD_EFIDEBUG, since we will need it to boot our kernel.

make -j $(nproc)
popd

Running QEMU

Make sure swtpm is installed and running on your system. For debian and friends there's a swtpm package, so just do

sudo apt install swtpm
mkdir /tmp/mytpm1
swtpm socket --tpmstate dir=/tmp/mytpm1 \
    --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
    --log level=40 --tpm2 &

and launch QEMU with swtpm support

sudo qemu-system-aarch64 \
    -bios u-boot.bin \
    -machine virt,gic-version=3,accel=kvm \
    -cpu host -m 4G \
    -nographic -no-acpi \
    -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
    -tpmdev emulator,id=tpm0,chardev=chrtpm \
    -device tpm-tis-device,tpmdev=tpm0 \
    -drive id=disk0,file=rootfs-linaro-buster-raw-unknown-20200720-440.ext4,if=none,format=raw \
    -device virtio-blk-device,drive=disk0

Booting linux

From U-Boot's command line do something along the lines of

tpm2 startup TPM2_SU_CLEAR && virtio scan 
efidebug boot add -b ABE0 'kernel' virtio 0 boot/Image -s 'root=/dev/vda'
efidebug boot order ABE0
bootefi bootmgr

If everything is compiled and launched correctly, you should see the kernel reporting the location of some related EventLog pointers.

efi: EFI v2.80 by Das U-Boot
efi: TPMFinalLog=0x13ddcc040 RTPROP=0x13ddcb040 SMBIOS=0xffffe000 TPMEventLog=0x13ddc4040 MEMRESERVE=0x13ddc3040 

Reading the EventLog

I am using a debian .ext4 image, where I have installed the latest tpm2 tools. If you don't have them install them with

sudo apt install tpm2-tools

The kernel exposes the eventlog in /sys. So you can read it with:

tpm2_eventlog /sys/kernel/security/tpm0/binary_bios_measurements
---
events:
  - EventNum: 0
    PCRIndex: 0
    EventType: EV_NO_ACTION
    Digest: "0000000000000000000000000000000000000000"
    EventSize: 37
    SpecID:
      - Signature: Spec ID Event03
        platformClass: 0
        specVersionMinor: 0
        specVersionMajor: 2
        specErrata: 2
        uintnSize: 2
        numberOfAlgorithms: 2
        Algorithms:
          - Algorithm[0]:
            algorithmId: sha1
            digestSize: 20
          - Algorithm[1]:
            algorithmId: sha256
            digestSize: 32
        vendorInfoSize: 0
  - EventNum: 1
    PCRIndex: 0
    EventType: EV_S_CRTM_VERSION
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "0772fd675fbebcdd4401008ee8d609760c1675df"
      - AlgorithmId: sha256
        Digest: "69f66450f9a8780cf2fbab358d46b8fabd4b7e9ae886b3d80083646c30e91b4c"
    EventSize: 74
    Event: "552d426f6f7420323032312e31302d7263322d30303031302d67643536666231666138352d646972747920284175672032342032303231202d2030363a33343a3335202b303830302900"
  - EventNum: 2
    PCRIndex: 7
    EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "57cd4dc19442475aa82743484f3b1caa88e142b8"
      - AlgorithmId: sha256
        Digest: "115aa827dbccfb44d216ad9ecfda56bdea620b860a94bed5b7a27bba1c4d02d8"
    EventSize: 53
    Event:
      VariableName: 61dfe48b-ca93-d211-aa0d-00e098032b8c
      UnicodeNameLength: 10
      VariableDataLength: 1
      UnicodeName: SecureBoot
      VariableData: "00"
  - EventNum: 3
    PCRIndex: 7
    EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9b1387306ebb7ff8e795e7be77563666bbf4516e"
      - AlgorithmId: sha256
        Digest: "dea7b80ab53a3daaa24d5cc46c64e1fa9ffd03739f90aadbd8c0867c4a5b4890"
    EventSize: 36
    Event:
      VariableName: 61dfe48b-ca93-d211-aa0d-00e098032b8c
      UnicodeNameLength: 2
      VariableDataLength: 0
      UnicodeName: PK
  - EventNum: 4
    PCRIndex: 7
    EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9afa86c507419b8570c62167cb9486d9fc809758"
      - AlgorithmId: sha256
        Digest: "e670e121fcebd473b8bc41bb801301fc1d9afa33904f06f7149b74f12c47a68f"
    EventSize: 38
    Event:
      VariableName: 61dfe48b-ca93-d211-aa0d-00e098032b8c
      UnicodeNameLength: 3
      VariableDataLength: 0
      UnicodeName: KEK
  - EventNum: 5
    PCRIndex: 7
    EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "5bf8faa078d40ffbd03317c93398b01229a0e1e0"
      - AlgorithmId: sha256
        Digest: "baf89a3ccace52750c5f0128351e0422a41597a1adfd50822aa363b9d124ea7c"
    EventSize: 36
    Event:
      VariableName: cbb219d7-3a3d-9645-a3bc-dad00e67656f
      UnicodeNameLength: 2
      VariableDataLength: 0
      UnicodeName: db
  - EventNum: 6
    PCRIndex: 7
    EventType: EV_EFI_VARIABLE_DRIVER_CONFIG
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "734424c9fe8fc71716c42096f4b74c88733b175e"
      - AlgorithmId: sha256
        Digest: "9f75b6823bff6af1024a4e2036719cdd548d3cbc2bf1de8e7ef4d0ed01f94bf9"
    EventSize: 38
    Event:
      VariableName: cbb219d7-3a3d-9645-a3bc-dad00e67656f
      UnicodeNameLength: 3
      VariableDataLength: 0
      UnicodeName: dbx
  - EventNum: 7
    PCRIndex: 4
    EventType: EV_EFI_BOOT_SERVICES_APPLICATION
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "d2702383b2e042ebefbb318f9382fd094c1c2d6b"
      - AlgorithmId: sha256
        Digest: "8fb6a4c7a0c7e7f22b944906eb07786cd3860394c7929e7c0768b2c99a2a3d87"
    EventSize: 162
    Event:
      ImageLocationInMemory: 0x7adb3000
      ImageLengthInMemory: 893720
      ImageLinkTimeAddress: 0x0
      LengthOfDevicePath: 130
      DevicePath: "01041400b9731de684a3cc4aaeab82e828f3628b031d050002031d05000104012a0001000000009800000000000000f805000000000050641c65888b6b418f2257061a9dc3c50202040436005c004500460049005c00640065006200690061006e005c007300680069006d0061006100360034002e0065006600690000007fff0400"
  - EventNum: 8
    PCRIndex: 1
    EventType: Unknown event type
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "50eb6bd100c48e81644d666a437725f49c6aed3c"
      - AlgorithmId: sha256
        Digest: "eb881b78feeb95756141a8d5358b891b297fad61b296f667de1f59b66bc92f4f"
    EventSize: 52
    Event: "61dfe48bca93d211aa0d00e098032b8c0900000000000000020000000000000042006f006f0074004f0072006400650072000000"
  - EventNum: 9
    PCRIndex: 1
    EventType: Unknown event type
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "74e29a0674816dfdfc2c2e9cbbcec357132da4e8"
      - AlgorithmId: sha256
        Digest: "5d123811f51e2e46c437c7e88e07053c81f4e63da3f11de8a8a2afb5334db137"
    EventSize: 198
    Event: "61dfe48bca93d211aa0d00e098032b8c0800000000000000960000000000000042006f006f0074003000300030003000010000008200640065006200690061006e00000001041400b9731de684a3cc4aaeab82e828f3628b031d050002031d05000104012a0001000000009800000000000000f805000000000050641c65888b6b418f2257061a9dc3c50202040436005c004500460049005c00640065006200690061006e005c007300680069006d0061006100360034002e0065006600690000007fff0400"
  - EventNum: 10
    PCRIndex: 4
    EventType: EV_EFI_ACTION
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "cd0fdb4531a6ec41be2753ba042637d6e5f7f256"
      - AlgorithmId: sha256
        Digest: "3d6772b4f84ed47595d72a2c4c5ffd15f5bb72c7507fe26f2aaee2c69d5633ba"
    EventSize: 40
    Event: 'Calling EFI Application from Boot Option'
  - EventNum: 11
    PCRIndex: 0
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 12
    PCRIndex: 1
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 13
    PCRIndex: 2
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 14
    PCRIndex: 3
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 15
    PCRIndex: 4
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 16
    PCRIndex: 5
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 17
    PCRIndex: 6
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 18
    PCRIndex: 7
    EventType: EV_SEPARATOR
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "9069ca78e7450a285173431b3e52c5c25299e473"
      - AlgorithmId: sha256
        Digest: "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
    EventSize: 4
    Event: "00000000"
  - EventNum: 19
    PCRIndex: 5
    EventType: EV_EFI_ACTION
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "443a6b7b82b7af564f2e393cd9d5a388b7fa4a98"
      - AlgorithmId: sha256
        Digest: "d8043d6b7b85ad358eb3b6ae6a873ab7ef23a26352c5dc4faa5aeedacf5eb41b"
    EventSize: 29
    Event: 'Exit Boot Services Invocation'
  - EventNum: 20
    PCRIndex: 5
    EventType: EV_EFI_ACTION
    DigestCount: 2
    Digests:
      - AlgorithmId: sha1
        Digest: "475545ddc978d7bfd036facc7e2e987f48189f0d"
      - AlgorithmId: sha256
        Digest: "b54f7542cbd872a81a9d9dea839b2b8d747c7ebd5ea6615c40f42f44a6dbeba0"
    EventSize: 40
    Event: 'Exit Boot Services Returned with Success'
pcrs:
  sha1:
    0  : 0x3e26be54f5f15140afbe509cc4580538d979598d
    1  : 0x5b4c188c39baa249f688460a63b68df6d3d3ec94
    2  : 0xb2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
    3  : 0xb2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
    4  : 0x260ae65533f38ab643f157bd176c72f9fdece410
    5  : 0xd16d7e629fd8d08ca256f9ad3a3a1587c9e6cc1b
    6  : 0xb2a83b0ebf2f8374299a5b2bdfc31ea955ad7236
    7  : 0x518bd167271fbb64589c61e43d8c0165861431d8
  sha256:
    0  : 0x7f35c1ef1bb7b9d2aee58ec4c36cf384d70524c2ce2b6801772d7fdb1d2b5f5a
    1  : 0xf35b74319598e48a6a69a6a04e903a872558b891563b0af23c877c8472c277a6
    2  : 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969
    3  : 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969
    4  : 0xbe4d7464e3a3c0a04040355368006a5fbe02c0ef232c8c18926df9b718374f36
    5  : 0xa5ceb755d043f32431d63e39f5161464620a3437280494b5850dc1b47cc074e0
    6  : 0x3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969
    7  : 0x65caf8dd1e0ea7a6347b635d2b379c93b9a1351edc2afc3ecda700e534eb3068